
#include "Config.h"
#include "reg.h"
#include "typedefs.h"
#include "Printf.h"
#include "I2C.h"
#include "CPU.h"
#include "Global.h"
#include "KeyRemo.h"
#include "dv_api.h"
#include "app_SRC.h"

typedef struct _PIP_POS_XY{
	WORD x;
	WORD y;
}PIP_POS_XY;

typedef struct _MODE_STATE{
	BYTE mdflg;
	//mdflg [bit0:MainUpdate|bit1:Pip0Update|bit2:Pip1Update|bit3:MainMute|bit4:Pip0Mute|bit5:Pip1Mute|bit6:Pip0En|bit7:Pip1En]
	INPORT inport[MAXOUTPORT];
	DISPMODE dispmd[MAXOUTPORT];
	PIP_POS_XY startpt;
	SIGFMT fmt[MAXOUTPORT];
	APP_PIP_MODE pipmode;
}MODE_STATE;
	

MODE_STATE ModeState;

CODE PIP_POS_XY WinXY[MAXPOS][MAXSIZE] = {
	{{0,  0},   {0,  0},  {0,0}},
	{{400,0},   {200,0},  {1,0}},
	{{0,  240}, {0,  80}, {0,1}},
	{{400,240}, {200,80}, {1,1}}
};

CODE BYTE Main_PIP0_MIX_SRC[MAXSRC] = {
	0x3d,   //0011 1101
	0x3e,   //0011 1110
	0x37,   //0011 0111
	0x3b,   //0011 1011
	0x1f,   //0001 1111
	0x0f    //0000 1111
};

void TaskSRC(void)
{
	SIGFMT sigfmt = NOTDET;
	BOOL isMute = FALSE;

	//Main Check
	do{
		isMute = TW8823OutPortMuteDetect(MAINWIN);
		sigfmt = TW8823SigFmtDetect(ModeState.inport[MAINWIN]);
		//Printf("\r\nMainCheck");

		if((sigfmt != NOTDET)&&(sigfmt != ModeState.fmt[MAINWIN])){
			TW8823OutPortMute(MAINWIN, TRUE);
			TW8823SigFmtSet(sigfmt);
			TW8823ModeSet(sigfmt, ModeState.dispmd[MAINWIN]);
			ModeState.fmt[MAINWIN] = sigfmt;
		}else if((sigfmt == NOTDET)&&(!isMute)){
			TW8823OutPortMute(MAINWIN, TRUE);
			TW8823SigFmtSet(NTSC);
			TW8823ModeSet(NTSC, ModeState.dispmd[MAINWIN]);
			ModeState.fmt[MAINWIN] = NTSC;
			break;
		}

		if((sigfmt != NOTDET)&&(isMute)&&((ModeState.mdflg & 0x08) == 0)){
			TW8823OutPortMute(MAINWIN, FALSE);
			break;
		}else{
			break;
		}
	}while(1);

	
	//PIP0 Check
	do{
		//Printf("\r\nPIP0Check");
		if((ModeState.mdflg & 0x40)==0){
			break;
		}

		isMute = TW8823OutPortMuteDetect(PIP0WIN);
		sigfmt = TW8823SigFmtDetect(ModeState.inport[PIP0WIN]);

		if((sigfmt != NOTDET)&&(sigfmt != ModeState.fmt[PIP0WIN])){
			TW8823OutPortMute(PIP0WIN, TRUE);
			TW8823SigFmtSet(sigfmt);
			TW8823ModeSet(sigfmt, ModeState.dispmd[PIP0WIN]);
			ModeState.fmt[PIP0WIN] = sigfmt;
		}else if((sigfmt == NOTDET)&&(!isMute)){
			TW8823OutPortMute(PIP0WIN, TRUE);
			TW8823SigFmtSet(NTSC);
			TW8823ModeSet(NTSC, ModeState.dispmd[PIP0WIN]);
			ModeState.fmt[PIP0WIN] = NTSC;
			break;
		}

		if((sigfmt != NOTDET)&&(isMute)&&((ModeState.mdflg & 0x10) == 0)){
			TW8823OutPortMute(PIP0WIN, FALSE);
			break;
		}else{
			break;
		}
	}while(1);
	
	//PIP1 Check
	do{
		//Printf("\r\nPIP1Check");
		if((ModeState.mdflg & 0x80)==0){
			break;
		}

		isMute = TW8823OutPortMuteDetect(PIP1WIN);
		sigfmt = TW8823SigFmtDetect(ModeState.inport[PIP1WIN]);

		if((sigfmt != NOTDET)&&(sigfmt != ModeState.fmt[PIP1WIN])){
			TW8823OutPortMute(PIP1WIN, TRUE);
			TW8823SigFmtSet(sigfmt);
			TW8823ModeSet(sigfmt, ModeState.dispmd[PIP1WIN]);
			ModeState.fmt[PIP1WIN] = sigfmt;
		}else if((sigfmt == NOTDET)&&(!isMute)){
			TW8823OutPortMute(PIP1WIN, TRUE);
			TW8823SigFmtSet(NTSC);
			TW8823ModeSet(NTSC, ModeState.dispmd[PIP1WIN]);
			ModeState.fmt[PIP1WIN] = NTSC;
			break;
		}

		if((sigfmt != NOTDET)&&(isMute)&&((ModeState.mdflg & 0x20) == 0)){
			TW8823OutPortMute(PIP1WIN, FALSE);
			break;
		}else{
			break;
		}
	}while(1);

	return;
}

void Init_SRCAPP(void)
{
	TW8823ModeInit();

	ModeState.inport[MAINWIN] = CVBS_Y0;
	ModeState.fmt[MAINWIN] = NTSC;
	ModeState.dispmd[MAINWIN] = FULL_800x480;
	
	ModeState.inport[PIP0WIN] = CVBS_Y0;
	ModeState.fmt[PIP0WIN] = NTSC;
	ModeState.dispmd[PIP0WIN] = SMALL_400x240;
	ModeState.startpt.x = WinXY[LEFT_TOP][SMALL].x;
	ModeState.startpt.y = WinXY[LEFT_TOP][SMALL].y;
	
	ModeState.inport[PIP1WIN] = CVBS_Y0;
	ModeState.fmt[PIP1WIN] = NTSC;
	ModeState.dispmd[PIP1WIN] = DUAL1_400x240;
	
	ModeState.mdflg = 0x00;
	ModeState.pipmode = PIP_OFF;
	Update_Mode(); 

	return;
}

void Change_MainSrc(APP_SRC src)
{
	switch (src){
	case CVBS:
		ModeState.inport[MAINWIN] = CVBS_Y0;
		break;
	case SVIDEO:
		ModeState.inport[MAINWIN] = YC_Y1C;
		break;
	case EXCVBS:
		ModeState.inport[MAINWIN] = EX_CVBS_Y0;
		break;
	case EXSVIDEO:
		ModeState.inport[MAINWIN] = EX_YC_Y1;
		break;
	case PC:
		ModeState.inport[MAINWIN] = ARGB_HV;
		break;
	case YPBPR:
		ModeState.inport[MAINWIN] = ARGB_SOG;
		break;
	default:
		ModeState.inport[MAINWIN] = CVBS_Y0;
		break;
	}

	ModeState.mdflg |= 0x01;
	//Update_Mode();
	return;
}

void Change_PIPSrc(APP_SRC src)
{
	switch (src){
	case CVBS:
		ModeState.inport[PIP0WIN] = CVBS_Y0;
		break;
	case SVIDEO:
		ModeState.inport[PIP0WIN] = YC_Y1C;
		break;
	case EXCVBS:
		ModeState.inport[PIP0WIN] = EX_CVBS_Y0;
		break;
	case EXSVIDEO:
		ModeState.inport[PIP0WIN] = EX_YC_Y1;
		break;
	case PC:
		ModeState.inport[PIP0WIN] = ARGB_HV;
		break;
	case YPBPR:
		ModeState.inport[PIP0WIN] = ARGB_SOG;
		break;
	default:
		ModeState.inport[PIP0WIN] = CVBS_Y0;
		break;
	}

	ModeState.mdflg |= 0x02;
	//Update_Mode();
	return;
}

void Change_PIPPosSize(APP_PIP_POS pos, APP_PIP_SIZE size)
{
	switch (size){
	case SMALL:
		ModeState.dispmd[PIP0WIN] = DUAL0_400x240;//SMALL_400x240;  //fix bug; use SMALL_400x240, the code will break down; erek 20121121
		break;
	case MIDDLE:
		ModeState.dispmd[PIP0WIN] = POP_400x480;//MIDDLE_600x400;//fix bug; use MIDDLE_600x400, the code will break down; erek 20121121
		break;
	case LARGE:
		ModeState.dispmd[PIP0WIN] = LARGE_800x480;
		break;
	default:
		ModeState.dispmd[PIP0WIN] = DUAL0_400x240;//SMALL_400x240; //fix bug; use SMALL_400x240, the code will break down; erek 20121121
		break;
	}
	
	ModeState.startpt.x = WinXY[pos][size].x;
	ModeState.startpt.y = WinXY[pos][size].y;

	ModeState.mdflg |= 0x02;
	//Update_Mode();
	return;
}

void Change_PIPMode(APP_PIP_MODE mode)
{
	switch (mode){
	case PIP_OFF:
		ModeState.dispmd[MAINWIN] = FULL_800x480;
		ModeState.mdflg &= 0x3f;
		break;
	case PIP_ON:
		ModeState.dispmd[MAINWIN] = FULL_800x480;
		ModeState.dispmd[PIP0WIN] =DUAL0_400x240; //SMALL_400x240;//fix bug; use SMALL_400x240, the code will break down; erek 20121121
		ModeState.startpt.x = WinXY[LEFT_TOP][SMALL].x;
		ModeState.startpt.y = WinXY[LEFT_TOP][SMALL].y;
		ModeState.mdflg &= 0x7f;
		ModeState.mdflg |= 0x40;
		break;
	case POP_ON:
		ModeState.dispmd[MAINWIN] = HALF_400x480;
		ModeState.dispmd[PIP0WIN] = POP_400x480;
		ModeState.startpt.x = 401;
		ModeState.startpt.y = 0;
		ModeState.mdflg &= 0x7f;
		ModeState.mdflg |= 0x40;
		break;
	case DUAL_ON:
		ModeState.inport[MAINWIN] = CVBS_Y0;
		ModeState.dispmd[MAINWIN] = HALF_400x480;
		
		ModeState.inport[PIP0WIN] = EX_CVBS_Y0;
		ModeState.dispmd[PIP0WIN] = DUAL0_400x240;
		ModeState.startpt.x = 402;
		ModeState.startpt.y = 0;
		
		ModeState.inport[PIP1WIN] = ARGB_SOG;
		ModeState.dispmd[PIP1WIN] = DUAL1_400x240;

		ModeState.mdflg |= 0xc0;
		break;
	case PIP_SHOW:
		ModeState.inport[PIP0WIN] = CVBS_Y0;
		ModeState.dispmd[PIP0WIN] = SMALL_400x240;
		ModeState.startpt.x = 20;
		ModeState.startpt.y = 100;
		ModeState.mdflg &= 0x7f;
		ModeState.mdflg |= 0x40;
		break;
	default:
		break;
	}

	switch ((ModeState.pipmode<<4)|mode){
	case ((PIP_OFF<<4)|PIP_ON):
	case ((PIP_OFF<<4)|PIP_SHOW):
	case ((PIP_ON<<4)|PIP_OFF):
	case ((PIP_ON<<4)|PIP_SHOW):
	case ((PIP_SHOW<<4)|PIP_OFF):
	case ((PIP_SHOW<<4)|PIP_ON):
		ModeState.mdflg &= 0xf8;
		ModeState.mdflg |= 0x03;
		break;
	case ((PIP_OFF<<4)|POP_ON):
	case ((PIP_ON<<4)|POP_ON):
	case ((PIP_SHOW<<4)|POP_ON):
	case ((POP_ON<<4)|PIP_OFF):
	case ((POP_ON<<4)|PIP_ON):
	case ((POP_ON<<4)|PIP_SHOW):
		ModeState.mdflg &= 0xf8;
		ModeState.mdflg |= 0x03;
		break;
	case ((PIP_OFF<<4)|DUAL_ON):
	case ((PIP_ON<<4)|DUAL_ON):
	case ((POP_ON<<4)|DUAL_ON):
	case ((PIP_SHOW<<4)|DUAL_ON):
	case ((DUAL_ON<<4)|PIP_OFF):
	case ((DUAL_ON<<4)|PIP_ON):
	case ((DUAL_ON<<4)|POP_ON):
	case ((DUAL_ON<<4)|PIP_SHOW):
		ModeState.mdflg &= 0xf8;
		ModeState.mdflg |= 0x07;
		break;
	case ((PIP_OFF<<4)|PIP_OFF):
	case ((PIP_ON<<4)|PIP_ON):
	case ((POP_ON<<4)|POP_ON):
	case ((DUAL_ON<<4)|DUAL_ON):
	case ((PIP_SHOW<<4)|PIP_SHOW):
	default:
		ModeState.mdflg &= 0xf8;
		break;
	}
	ModeState.pipmode = mode;

	//Update_Mode();
	return;
}

BOOL IsAvailabe(APP_SRC MainSrc, APP_SRC PIP0Src)
{
	return ((BOOL)((Main_PIP0_MIX_SRC[MainSrc]>>PIP0Src)&0x0001));
}

void Change_PIPMute(BOOL mute)
{
	//Printf("\r\n PIPMute %bd", mute);
	if(mute){
		ModeState.mdflg |= 0x10;
	}else{
		ModeState.mdflg &= 0xef;
	}
	
	ModeState.mdflg |= 0x02;
	return;
}

void Update_Mode(void)
{
	//Main
	if(ModeState.mdflg & 0x01){
		//Printf("\r\n Main");
		TW8823OutPortMute(MAINWIN, TRUE);
		TW8823InPortSet(ModeState.inport[MAINWIN]);
		TW8823OutPortSet(MAINWIN);
		TW8823ModeSet(ModeState.fmt[MAINWIN], ModeState.dispmd[MAINWIN]);
		ModeState.mdflg &= 0xfe;
	}

	//PIP0
	if((ModeState.mdflg & 0x02)==0x02){
		//Printf("\r\n PIP0");
		if((ModeState.mdflg & 0x40)==0x40){
			TW8823OutPortMute(PIP0WIN, TRUE);
			TW8823InPortSet(ModeState.inport[PIP0WIN]);
			TW8823OutPortSet(PIP0WIN);
			TW8823ModeSet(ModeState.fmt[PIP0WIN], ModeState.dispmd[PIP0WIN]);
			TW8823OutPosSet(PIP0WIN, ModeState.startpt.x, ModeState.startpt.y);
			TW8823OutPortEn(PIP0WIN, TRUE);
		}else{
			TW8823OutPortEn(PIP0WIN, FALSE);
			TW8823OutPortMute(PIP0WIN, TRUE);
		}
		ModeState.mdflg &= 0xfd;
	}

	//PIP1
	if((ModeState.mdflg & 0x04)==0x04){
		//Printf("\r\n PIP1");
		if((ModeState.mdflg & 0x80)==0x80){
			TW8823OutPortMute(PIP1WIN, TRUE);
			TW8823InPortSet(ModeState.inport[PIP1WIN]);
			TW8823OutPortSet(PIP1WIN);
			TW8823ModeSet(ModeState.fmt[PIP1WIN], ModeState.dispmd[PIP1WIN]);
			TW8823OutPosSet(PIP1WIN, 402, 241);
			TW8823OutPortEn(PIP1WIN, TRUE);
		}else{
			TW8823OutPortEn(PIP1WIN, FALSE);
			TW8823OutPortMute(PIP1WIN, TRUE);
		}
		ModeState.mdflg &= 0xfb;
	}

	TaskSRC();
	return;
}

void Change_PIPTrans(BYTE val)
{
	WriteTW88(0xff, 0x06);
	WriteTW88(0x80, val);
}


void Set_Brightness(BYTE val)
{
	WriteTW88(0xff, 0x05);
	WriteTW88(0x0a, val);
	WriteTW88(0x1a, val);
}

void Set_Contrast(BYTE val)
{
	WriteTW88(0xff, 0x05);
	WriteTW88(0x04, val);
	WriteTW88(0x14, val);
}

void Set_Hue(BYTE val)
{
	WriteTW88(0xff, 0x05);
	WriteTW88(0x00, val);
	WriteTW88(0x10, val);
}


